package cn.wanda.bi.sunshine.platform.server.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Stream;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import cn.wanda.bi.sunshine.platform.server.bean.mapper.DimColumnLabelMapper;
import cn.wanda.bi.sunshine.platform.server.bean.mapper.DimColumnLabelValueMapper;
import cn.wanda.bi.sunshine.platform.server.bean.model.DimColumnLabel;
import cn.wanda.bi.sunshine.platform.server.bean.model.DimColumnLabelExample;
import cn.wanda.bi.sunshine.platform.server.bean.model.DimColumnLabelValue;
import cn.wanda.bi.sunshine.platform.server.bean.model.DimColumnLabelValueExample;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.Aggs;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.AggsField1Field2;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.AggsField1Field2Aggs;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.Distinct_w_request;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.Distinct_w_requestField1Field2;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.Distinct_w_requestField1Field2Aggs;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.ElasticSearchQueryForDistinct;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.ElasticSearchQueryForDistinctField1Field2;
import cn.wanda.bi.sunshine.platform.server.client.request.elasticsearch.Terms;
import cn.wanda.bi.sunshine.platform.server.client.response.elasticsearch.UserLabelBean;
import cn.wanda.bi.sunshine.platform.server.client.wrapper.ElasticSearchClientWrapper;
import cn.wanda.bi.sunshine.platform.server.controller.request.DimLabelAllRequest;
import cn.wanda.bi.sunshine.platform.server.controller.request.LabelQueryRequest;
import cn.wanda.bi.sunshine.platform.server.controller.response.common.ListResponse;
import cn.wanda.bi.sunshine.platform.server.controller.response.common.SimpleResponse;
import cn.wanda.bi.sunshine.platform.server.utils.JsonUtil;
import cn.wanda.bi.sunshine.platform.server.utils.PasswordUtil;

/**
 * Created by James on 17/7/21.
 */
@Service
public class LabelDictionaryService {

    public static final Logger logger = LoggerFactory.getLogger(LabelDictionaryService.class);

    @Autowired
    private ElasticSearchClientWrapper elasticSearchClientWrapper;
    @Autowired
    private DimColumnLabelMapper dimColumnLabelMapper;
    @Autowired
    private DimColumnLabelValueMapper dimColumnLabelValueMapper;
    @Autowired
    private LabelService labelService;

    public ListResponse queryUserLabelAll(Integer limit, Integer index, DimLabelAllRequest request) {
        DimColumnLabelExample dimColumnLabelExample = new DimColumnLabelExample();
        dimColumnLabelExample.setOffset(index * limit - limit);
        dimColumnLabelExample.setLimit(limit);
        DimColumnLabelExample.Criteria criteria = dimColumnLabelExample.createCriteria();
        if (request != null) {
            if (request.getBoxFlag() != null)
                criteria.andBoxFlagEqualTo(request.getBoxFlag());
            if (request.getColumnCategory() != null)
                criteria.andColumnCategoryEqualTo(request.getColumnCategory());
            if (request.getColumnId() != null)
                criteria.andColumnIdEqualTo(request.getColumnId());
            if (request.getColumnName() != null)
                criteria.andColumnNameEqualTo(request.getColumnName());
            if (request.getColumnSource() != null)
                criteria.andColumnSourceEqualTo(request.getColumnSource());
            if (request.getColumnType() != null)
                criteria.andColumnTypeEqualTo(request.getColumnType());
            if (request.getConditionSource() != null)
                criteria.andConditionSourceEqualTo(request.getConditionSource());
            if (request.getCurrentValue() != null)
                criteria.andCurrentValueEqualTo(request.getCurrentValue());
            if (request.getDatabaseSource() != null)
                criteria.andDatabaseSourceEqualTo(request.getDatabaseSource());
            if (request.getIsValid() != null)
                criteria.andIsValidEqualTo(request.getIsValid());
            if (request.getTableSource() != null)
                criteria.andTableSourceEqualTo(request.getTableSource());
            if (request.getVersion() != null)
                criteria.andVersionEqualTo(request.getVersion());
        }
        int count = dimColumnLabelMapper.countByExample(dimColumnLabelExample);
        List<DimColumnLabel> userLabelAllSupportedFieldsList = dimColumnLabelMapper
                .selectByExample(dimColumnLabelExample);
        return ListResponse.success(userLabelAllSupportedFieldsList, count, index, limit);
    }

    @Cacheable(value = "cache:dimcolumnlabelvalue", key = "'cache:dimcolumnlabelvalue:label:'+#label")
    public List<DimColumnLabelValue>  getDimColumnLabelValues(String label){
    	DimColumnLabelValueExample dimColumnLabelValueExample = new DimColumnLabelValueExample();
        DimColumnLabelValueExample.Criteria criteria = dimColumnLabelValueExample.createCriteria();
        criteria.andLabelEqualTo(label);
        List<DimColumnLabelValue> userLabelAllSupportedFieldsValueList = dimColumnLabelValueMapper
                .selectByExample(dimColumnLabelValueExample);
        return userLabelAllSupportedFieldsValueList;
    }

    @Cacheable(value = "cache:dimcolumnlabelvalue", key = "'cache:dimcolumnlabelvalue:queryversionvalues'")
    public SimpleResponse queryVersionValues() {
        DimColumnLabelExample dimColumnLabelExample = new DimColumnLabelExample();
        DimColumnLabelExample.Criteria criteria = dimColumnLabelExample.createCriteria();
        criteria.andIsValidEqualTo(1);
        List<DimColumnLabel> dimColumnLabels = dimColumnLabelMapper.selectByExample(dimColumnLabelExample);

        Stream<DimColumnLabel> ret = dimColumnLabels.stream().distinct();
        List<String> versions = new ArrayList<>();
        StringBuffer tmp = new StringBuffer();
        ret.forEach(p -> {
            String ver = p.getVersion().trim();
            if (StringUtils.isNotEmpty(ver)) {
                if (versions != null && versions.size() > 0) {
                    if (!tmp.toString().contains(ver)) {
                        versions.add(p.getVersion());
                        tmp.append(ver + ",");
                    }
                } else {
                    versions.add(p.getVersion());
                    tmp.append(ver + ",");
                }
            }

        });

        return SimpleResponse.success(versions);
    }

    @CacheEvict(value = "cache:dimcolumnlabelvalue", key = "'cache:dimcolumnlabelvalue:'+#label")
    public SimpleResponse deleteByLabel(String label) {
        DimColumnLabelValueExample dimColumnLabelValueExample = new DimColumnLabelValueExample();
        DimColumnLabelValueExample.Criteria criteria = dimColumnLabelValueExample.createCriteria();
        if (StringUtils.isNotEmpty(label)) {
            criteria.andLabelEqualTo(label);
        }
        dimColumnLabelValueMapper.deleteByExample(dimColumnLabelValueExample);
        return SimpleResponse.success();
    }

    @CacheEvict(value = "cache:dimcolumnlabelvalue", key = "'cache:dimcolumnlabelvalue:'+#value.getLabel()")
    public SimpleResponse insert(DimColumnLabelValue value) {
        dimColumnLabelValueMapper.insert(value);
        return SimpleResponse.success(value);
    }

    public ElasticSearchQueryForDistinct getQuery(String label) {
        ElasticSearchQueryForDistinct query = new ElasticSearchQueryForDistinct();
        Terms terms = new Terms();
        terms.setField(label);
        Distinct_w_request distinct_w_request = new Distinct_w_request();
        distinct_w_request.setTerms(terms);
        Aggs aggs = new Aggs();
        aggs.setDistinct_w(distinct_w_request);
        query.setAggs(aggs);
        query.setSize(0);
        return query;
    }

    public UserLabelBean QueryUserValue(String label) {
        ElasticSearchQueryForDistinct query = getQuery(label);
		String cacheKey = PasswordUtil.MD5LowerCase(JsonUtil.toJson(query));
        UserLabelBean userLabelBean = elasticSearchClientWrapper.userLabelSearchForDistinct(query,cacheKey);
        return userLabelBean;
    }

    public UserLabelBean QueryUserValue(String label, LabelQueryRequest request) {
        ElasticSearchQueryForDistinct query = getQuery(label, request);
		String cacheKey = PasswordUtil.MD5LowerCase(JsonUtil.toJson(query));
        UserLabelBean userLabelBean = elasticSearchClientWrapper.userLabelSearchForDistinct(query,cacheKey);
        return userLabelBean;
    }

    public ElasticSearchQueryForDistinct getQuery(String label, LabelQueryRequest labelQueryRequest) {
        ElasticSearchQueryForDistinct query = new ElasticSearchQueryForDistinct();
        Terms terms = new Terms();
        terms.setField(label);
        Distinct_w_request distinct_w_request = new Distinct_w_request();
        distinct_w_request.setTerms(terms);
        Aggs aggs = new Aggs();
        aggs.setDistinct_w(distinct_w_request);
        query.setAggs(aggs);
        query.setSize(0);
        query.setQuery(labelService.getBoolQuery(labelQueryRequest));
        return query;
    }

    public UserLabelBean QueryUserValueField1Field2(String field1, String field2,
                                                    LabelQueryRequest labelQueryRequest) {
        ElasticSearchQueryForDistinctField1Field2 query = getQueryField1Field2(field1, field2, labelQueryRequest);
		String cacheKey = PasswordUtil.MD5LowerCase(JsonUtil.toJson(query));
        UserLabelBean userLabelBeanField1Field2 = elasticSearchClientWrapper.userLabelSearchForDistinctField1Field2(query,cacheKey);
        return userLabelBeanField1Field2;
    }

    public ElasticSearchQueryForDistinctField1Field2 getQueryField1Field2(String field1, String field2, LabelQueryRequest labelQueryRequest) {
        ElasticSearchQueryForDistinctField1Field2 query = new ElasticSearchQueryForDistinctField1Field2();
        Terms terms = new Terms();
        terms.setField(field1);
        Distinct_w_requestField1Field2 distinct_w_request = new Distinct_w_requestField1Field2();
        distinct_w_request.setTerms(terms);

        Terms terms2 = new Terms();
        terms2.setField(field2);
        Distinct_w_requestField1Field2Aggs distinct_w_request2 = new Distinct_w_requestField1Field2Aggs();
        distinct_w_request2.setTerms(terms2);

        AggsField1Field2Aggs aggsField1Field2Aggs = new AggsField1Field2Aggs();
        aggsField1Field2Aggs.setDistinct_w(distinct_w_request2);
        distinct_w_request.setAggs(aggsField1Field2Aggs);

        AggsField1Field2 aggs = new AggsField1Field2();
        aggs.setDistinct_w(distinct_w_request);

        query.setAggs(aggs);
        query.setSize(0);
        query.setQuery(labelService.getBoolQuery(labelQueryRequest));
        return query;
    }

}
